use crate::error::Error;
use derive_builder::Builder;
use serde::{Deserialize, Serialize};

use crate::{database::DataSource, modeling::ModelingVersion};

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "DomainTransformerUnitBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct DomainTransformerUnit {
    #[serde(rename = "domain_identifier")]
    pub domain_identifier: String,
    pub classes: Option<Vec<String>>,
}

#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
pub enum DomainTransformerFileFormat {
    #[default]
    #[serde(rename = "sqlite")]
    SQLite,
}

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "DomainTransformerFileOptionsBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct DomainTransformerFileOptions {
    pub version: ModelingVersion,
    pub format: DomainTransformerFileFormat,
}

#[derive(Debug, Serialize, Deserialize, Default, Clone, Builder, PartialEq)]
#[builder(name = "DomainTransformerOptionsBuilder")]
#[builder(pattern = "mutable")]
#[builder(setter(into, strip_option), default)]
#[builder(derive(Debug))]
#[builder(build_fn(error = "Error"))]
pub struct DomainTransformerOptions {
    pub ignore_errs: bool,
    pub file_options: Option<DomainTransformerFileOptions>,
    pub ddl: bool,
}

#[async_trait::async_trait]
pub trait DomainTransformer {
    /// 领域数据转移
    async fn transform_domain(
        &self,
        source: &DataSource,
        target: &DataSource,
        domains: Vec<DomainTransformerUnit>,
        options: DomainTransformerOptions,
    ) -> anyhow::Result<()>;

    /// 领域数据转移
    async fn write_file(
        &self,
        source: &DataSource,
        target: &String,
        domains: Vec<DomainTransformerUnit>,
        options: DomainTransformerOptions,
    ) -> anyhow::Result<()>;

    /// 领域数据转移
    async fn read_file(
        &self,
        source: &String,
        target: &DataSource,
        domains: Vec<DomainTransformerUnit>,
        options: DomainTransformerOptions,
    ) -> anyhow::Result<()>;

    /// 清空领域
    async fn clear_domain(
        &self,
        meta_datasource: &DataSource,
        domains: Vec<String>,
    ) -> anyhow::Result<()>;

    /// 删除领域
    async fn delete_domain(
        &self,
        meta_datasource: &DataSource,
        domains: Vec<String>,
    ) -> anyhow::Result<()>;
}
